import React, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useParams } from 'react-router-dom'
import {
  Card,
  Row,
  Col,
  Tree,
  Tag,
  Pagination,
  Table,
  Button,
  message,
} from 'antd'
import type { DataNode, TreeProps } from 'antd/es/tree'
import type { ColumnsType } from 'antd/es/table'
import {
  reqdepartment,
  reqScheduleRules,
  reqScheduleList,
} from '@api/hospital/hospitalList'
import {
  IdepartmentList,
  IscheduleRuleList,
  IsheduleDetailList,
  IScheduleDetail,
} from '@api/hospital/hospitalList/model/hospitalListTypes'

const columns: ColumnsType<IScheduleDetail> = [
  {
    title: '序号',
    render: (text, _, index) => index + 1,
    align: 'center',
  },
  {
    title: '职称',
    dataIndex: 'title',
  },
  {
    title: '号源时间',
    dataIndex: 'workDate',
  },
  {
    title: '可预约数',
    dataIndex: 'availableNumber',
  },
  {
    title: '剩余预约数',
    dataIndex: 'reservedNumber',
  },
  {
    title: '挂号费(元)',
    dataIndex: 'amount',
  },
  {
    title: '擅长技能',
    dataIndex: 'skill',
  },
]

let depcode: string // 当前科室的编码
export default function HospitalSchedule() {
  const navigate = useNavigate()
  // 当前医院的编码
  const { hoscode } = useParams()

  // 所有科室数据
  const [department, setDepartment] = useState<IdepartmentList>([])
  // 存储所有一级科室的depcode,
  const [depcodes, setDepcodes] = useState<string[]>([])

  // 排班规则数据
  const [scheduleRues, setScheduleRues] = useState<IscheduleRuleList>([])

  // 排班详情数据
  const [scheduleDetails, setScheduleDetails] = useState<IsheduleDetailList>([])

  // 排班规则分页的状态
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(5)
  const [total, setTotal] = useState(5)

  // 面包屑相关的状态
  const [hosname, setHosname] = useState('')
  const [depname, setDepname] = useState('')
  const [workDate, setWorkDate] = useState('')

  useEffect(() => {
    async function fetch() {
      // 获取科室数据
      // 当一个异步函数里面的所有代码执行完毕,则异步函数返回的promise的状态会改成成功
      // 一个异步函数的返回值是什么,当异步函数执行完毕,promise会变成成功,成功的promise的value值就是异步函数中返回的内容
      depcode = await getDepartment()
      // 获取排班规则
      const workDate = await getScheduleRules(page, pageSize, depcode)
      // 获取排班详情
      getScheduleDetail(workDate)
    }
    fetch()
  }, [])

  // 获取科室数据的函数
  async function getDepartment() {
    // 需要传入hoscode
    const result = await reqdepartment(hoscode as string)

    // 给每一个一级科室的数据对象,添加属性disabled: true.就可以实现一级科室禁用效果
    result.forEach((item) => {
      item.disabled = true
    })
    setDepartment(result)

    //根据所有的科室数据,生成一个新数组,新数组中存放一级科室的depcode. 用于展示一级科室
    setDepcodes(
      result.map((item) => {
        return item.depcode // 一级科室的depcode
      })
    )

    // 将当前科室的名称存储起来
    setDepname(result[0].children[0].depname)

    // 把第一个一级科室里面的第一个二级科室的depcode返回出去
    return result[0].children[0].depcode
  }

  // 获取排班规则
  async function getScheduleRules(
    page: number,
    pageSize: number,
    depcode: string
  ) {
    const result = await reqScheduleRules(
      page,
      pageSize,
      hoscode as string,
      depcode
    )
    // console.log(result)
    // 存储当前排班规则列表
    setScheduleRues(result.bookingScheduleList)
    setTotal(result.total)

    // 存储排班规则里面的第一个排班的日期
    setWorkDate(result.bookingScheduleList[0]?.workDate)

    // 存储当前医院名称
    setHosname(result.baseMap.hosname)

    return result.bookingScheduleList[0]?.workDate
  }

  // 获取排班详情
  async function getScheduleDetail(workDate: string) {
    try {
      const result = await reqScheduleList(hoscode as string, depcode, workDate)
      setScheduleDetails(result)
    } catch (error) {
      // console.log('请求失败了', error)
      message.error('没有数据')
      // 将医院排班详情的表格数据设置为空
      setScheduleDetails([])
    }
  }

  const onSelect: TreeProps['onSelect'] = async (selectedKeys, info: any) => {
    console.log('selected', selectedKeys, info)
    // 修改面包屑的科室名称
    setDepname(info.node.depname)

    // 获取排班规则
    depcode = selectedKeys[0] as string
    setPage(1)
    const workDate = await getScheduleRules(1, pageSize, depcode)
    setWorkDate(workDate)
    // 获取排班详情
    // try {
    // trycatch可以捕获失败的promise
    // 注意: 调用getScheduleDetail发送请求,但是真正请求失败的是这个方法里面调用的req...所以,应该使用tryCatch包裹真正请求失败的那段代码.如果包裹这个函数是无法捕获的
    getScheduleDetail(workDate)
    // } catch (error) {
    // console.log('请求失败了', error)
    // }
  }

  // 根据当前页面的可视区的高度,动态计算左侧科室盒子的高度
  // 当前页面可视区高度 - header高度(64) -tabs高度(44) - Card上下内边距(48) - 面包屑高度(36)

  const wrappedHeight =
    document.documentElement.clientHeight - 64 - 44 - 48 - 36

  return (
    <Card>
      <p>
        选择：{hosname} / {depname} / {workDate}
      </p>
      {/* Row是antd中栅格系统的一行. Col是一列  span表示这一列在一行中占多少份(总共24份) */}
      <Row gutter={20}>
        <Col span={5}>
          <div
            style={{
              border: '1px solid #ccc',
              height: wrappedHeight,
              overflow: 'scroll',
            }}
          >
            <Tree
              // checkable // 是否添加复选框
              // defaultExpandedKeys={['0-0-0', '0-0-1']} // 默认展开的树节点.值就是treeData对应数据的key值
              // defaultSelectedKeys={['0-0-0', '0-0-1']} // 默认选中的树形节点数据
              // defaultCheckedKeys={['0-0-0', '0-0-1']} // 默认复选框被选中的属性节点
              onSelect={onSelect} // 选中节点的事件
              // onCheck={onCheck} // 切换复选框触发的事件
              //   注意: Tree组件默认渲染的是treeData数据中每一个对象的title和key
              // title是什么,就渲染对应的内容,key是这一条数据的唯一标识符,key在后面的逻辑中需要操作数据
              treeData={department as []} // 传递要被展示的数据
              // 告诉Tree渲染数据时,不要再去找title和key了,而是渲染depname和depcode
              fieldNames={{
                key: 'depcode',
                title: 'depname',
              }}
              // 设置一级科室展示, 数据是一个数组,这个数组中要存放的是所有的一级科室的depcode
              expandedKeys={depcodes}
            />
          </div>
        </Col>
        <Col span={19}>
          {scheduleRues.map((item) => {
            return (
              <Tag
                style={{
                  cursor: 'pointer',
                }}
                color={item.workDate === workDate ? 'green' : ''}
                key={item.workDate}
                onClick={() => {
                  // 修改workDate,则面包屑的日期会自动变化,并且高亮也会自动变化
                  setWorkDate(item.workDate)

                  // 获取排班详情数据
                  getScheduleDetail(item.workDate)
                }}
              >
                <div>
                  {item.workDate} {item.dayOfWeek}
                </div>
                <div>
                  {item.availableNumber} / {item.reservedNumber}
                </div>
              </Tag>
            )
          })}

          <Pagination
            current={page}
            pageSize={pageSize}
            total={total}
            showSizeChanger
            pageSizeOptions={[5, 10]}
            style={{ marginTop: 20, marginBottom: 20 }}
            onChange={async (page, pageSize) => {
              setPage(page)
              setPageSize(pageSize)
              const workDate = await getScheduleRules(page, pageSize, depcode)
              getScheduleDetail(workDate)
            }}
          ></Pagination>
          {/* pagination={false} 表格不展示分页器 */}
          <Table
            columns={columns}
            dataSource={scheduleDetails}
            pagination={false}
            bordered
            rowKey={'id'}
          />
          <Button
            style={{ marginTop: 20 }}
            onClick={() => {
              navigate(-1)
            }}
          >
            返回
          </Button>
        </Col>
      </Row>
    </Card>
  )
}
